#ifndef _Ring_QUEUE_HPP_
#define _Ring_QUEUE_HPP_
#include <iostream>
#include <vector>
#include <pthread.h>
#include <Sem.hpp>
const int g_default_num = 5;
using namespace std;
template <class T>
class RingQueue
{
public:
    RingQueue(int default_num = g_default_num)
        : ring_queue_(default_num),
          num_(default_num), c_step(0), p_step(0),
          space_sem_(default_num),
          data_sem_(0) // 数据资源一开始是没有的
    {
        pthread_mutex_init(&clock, nullptr);
        pthread_mutex_init(&plock, nullptr);
    }
    ~RingQueue()
    {
        pthread_mutex_destroy(&clock, nullptr);
        pthread_mutex_destroy(&plock, nullptr);
    }
    // 生产者,关注空间资源
    void push(const T &in) // 如果消费者走得慢一点，那么生产者会一瞬间消耗完所有的空间资源（space_sem信号量一瞬间被减至0，然后阻塞）
    {
        // 可以使用static int index = 0;
        // ring_queue_[index++] = in;
        pthread_mutex_lock(&plock);
        space_sem_.P(); // 先预定一份空间资源（被使用，就递减）
        ring_queue_[p_step++] = in;
        p_step %= num_; // index = index % num_
        data_sem_.V();  // 数据资源增加
        pthread_mutex_unlock(&plock);
    }
    // 消费者
    void pop(T *out)
    {
        pthread_mutex_lock(&clock);
        data_sem_.P(); // 先预定一份数据资源（被消费，就递减）
        *out = ring_queue_[c_step++];
        c_step %= num_;
        space_sem_.V(); // 数据被消费后代表这个位置可以被腾出来了，所以空间资源递增
        pthread_mutex_unlock(&clock);
    }
    void debug()
    {
        std::cerr << "size: " << ring_queue_.size() << "num:" << num << std::endl;
    }

private:
    std::vector<T> ring_queue_;
    int num_;
    int c_step;            // 消费下标
    int p_step;            // 生产下标
    Sem space_sem_;        // 封装好的空间资源信号量
    Sem data_sem_;         // 封装好的数据资源信号量
    pthread_mutex_t clock; // 消费者的锁
    pthread_mutex_t plock; // 生产者的锁
};

#endif